Alt text

Comme nos 5 sens, les capteurs de téléphones peuvent donner des informations bien utiles pour certaines applications...

Contexte technique

Ce tutorial utilise une approche code-behind où toute la logique de gestion des capteurs est directement dans le fichier XAML.CS.

Pour utiliser l'accéléromètre, il faut l'activer et assigner une fonction qui sera appelée en cas de changement des données du capteur (la fréquence d'actualisation est adaptable...)

Aperçu

Alt text

XAML

Voici la structure XAML pour afficher les données de l'accéléromètre :

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloMaui1.SensorPage"
             Title="Sensors">

    <VerticalStackLayout>
        <Frame BorderColor="Red" Margin="5,5,5,0">
            <StackLayout>
                <Label x:Name="sensorValueLabel"
                       Text="Données du capteur: N/A"
                       VerticalOptions="Center"
                       HorizontalOptions="Center" />

                <Button x:Name="enableButton"
                        Text="Activer / Désactiver l'accéléromètre"
                        Clicked="OnEnableClicked" />

                <HorizontalStackLayout Margin="0,0,10,0">
                    <Label x:Name="enabledLabel" Text="on" IsVisible="False" />
                    <Label x:Name="disabledLabel" Text="off" IsVisible="True" />
                </HorizontalStackLayout>

                <BoxView x:Name="cancelIndicator"
                         Margin="0,10,0,0"
                         Color="Red"
                         HeightRequest="200"
                         WidthRequest="200" />

                <HorizontalStackLayout Margin="0,15,0,0">
                    <Label x:Name="thresholdLabel" Text="Seuil: 0" />
                    <Slider x:Name="thresholdSlider"
                            Minimum="-10"
                            Maximum="10"
                            WidthRequest="150"
                            ValueChanged="OnThresholdChanged" />
                </HorizontalStackLayout>

                <Label x:Name="accelerationLabel"
                       Margin="0,30,0,0"
                       Text="Acceleration: 0" />
            </StackLayout>
        </Frame>

        <Frame BorderColor="Green" Margin="5,10,5,0">
            <StackLayout>
                <Switch x:Name="shakeSwitch"
                        Toggled="OnShakeToggled" />
                <BoxView x:Name="shakeIndicator"
                         Color="Black"
                         WidthRequest="150"
                         HeightRequest="150" />
            </StackLayout>
        </Frame>
    </VerticalStackLayout>
</ContentPage>

Structure:

Code-behind

Voici l'implémentation complète dans le fichier XAML.CS:

Propriétés et champs

using System.Diagnostics;

public partial class SensorPage : ContentPage
{
    private string sensorValue;
    private bool enabled = false;
    private bool disabled = true;

    // Variables pour la détection de seuil avancée
    private bool cancel = false;
    private string cancelColor = "Red";
    private double threshold = 0;
    private double acceleration = 0;
    private Stopwatch stopwatch = new();

    // Variables pour la détection de secousses
    private string shakeColor = "Black";

    public SensorPage()
    {
        InitializeComponent();
    }
}

Ces variables permettent de:

Activation du capteur

private void OnEnableClicked(object sender, EventArgs e)
{
    if (Accelerometer.Default.IsSupported)
    {
        if (!Accelerometer.Default.IsMonitoring)
        {
            // Activer l'accéléromètre
            Accelerometer.Default.ReadingChanged += Accelerometer_ReadingChanged;
            Accelerometer.Default.Start(SensorSpeed.Default);

            enabled = true;
            disabled = false;

            // Mettre à jour l'UI
            MainThread.BeginInvokeOnMainThread(() =>
            {
                enabledLabel.IsVisible = true;
                disabledLabel.IsVisible = false;
            });
        }
        else
        {
            // Désactiver l'accéléromètre
            Accelerometer.Default.Stop();
            Accelerometer.Default.ReadingChanged -= Accelerometer_ReadingChanged;

            enabled = false;
            disabled = true;

            // Mettre à jour l'UI
            MainThread.BeginInvokeOnMainThread(() =>
            {
                enabledLabel.IsVisible = false;
                disabledLabel.IsVisible = true;
            });
        }
    }
}

Points importants:

Gestion du slider de seuil

private void OnThresholdChanged(object sender, ValueChangedEventArgs e)
{
    threshold = e.NewValue;
    MainThread.BeginInvokeOnMainThread(() =>
    {
        thresholdLabel.Text = $"Seuil: {threshold:F1}";
    });
}

Ce slider permet de définir un seuil d'accélération. Si l'accélération dépasse ce seuil pendant 3 secondes, le BoxView rouge deviendra bleu.

Fonction observateur (avec détection de seuil avancée)

private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)
{
    // Récupérer les valeurs X, Y, Z
    sensorValue = e.Reading.ToString();

    // Calcul avancé: détecter une inclinaison maintenue sur l'axe Y
    var data = e.Reading.Acceleration.Y;
    acceleration = Math.Sqrt(data * data); // Valeur absolue via racine carrée
    var thresholdPassed = acceleration >= threshold;

    if (thresholdPassed)
    {
        if (!cancel)
        {
            // Premier dépassement du seuil: démarrer le chronomètre
            stopwatch.Reset();
            stopwatch.Start();
            cancel = true;
        }
        else
        {
            // Seuil maintenu: vérifier si ça fait plus de 3 secondes
            if (stopwatch.ElapsedMilliseconds > 3000)
            {
                cancelColor = "Blue"; // Seuil maintenu pendant 3 secondes!
                stopwatch.Stop();
            }
        }
    }
    else
    {
        // Retour sous le seuil: réinitialiser
        cancel = false;
        cancelColor = "Red";
        stopwatch.Stop();
    }

    // Mettre à jour l'UI (nécessaire sur le thread principal)
    MainThread.BeginInvokeOnMainThread(() =>
    {
        sensorValueLabel.Text = $"Données du capteur: {sensorValue}";
        accelerationLabel.Text = $"Acceleration: {acceleration:F2}";
        cancelIndicator.Color = cancelColor == "Blue" ? Colors.Blue : Colors.Red;
    });
}

Explication:

Cas d'usage:
Cette logique pourrait servir à détecter une inclinaison prolongée du téléphone, par exemple pour annuler une action en maintenant le téléphone incliné pendant 3 secondes.

Simulateur

On peut stimuler l'accéléromètre en utilisant les outils avancés du simulateur:

Alt text

Virtual sensors

Alt text

Pour réagir à des secousses, il est nécessaire de faire un peu de calcul et définir un seuil de tolérance...
Tout cela est possible, néanmoins, MAUI intègre cela nativement et on peut donc réutiliser ce qui a déjà été implémenté...

XAML

La partie shake est déjà incluse dans le XAML complet ci-dessus (Frame vert):

Code-behind

Voici l'implémentation complète de la détection de secousses (la variable shakeColor est déjà déclarée en haut):

Méthode pour réagir au switch

private void OnShakeToggled(object sender, ToggledEventArgs e)
{
    ToggleShake(e.Value);
}

Cette méthode est appelée quand l'utilisateur change l'état du switch. Avec l'approche code-behind, on utilise simplement l'événement Toggled standard du Switch.

Méthode d'activation

private void ToggleShake(bool enable)
{
    if (Accelerometer.Default.IsSupported)
    {
        if (enable)
        {
            // Activer la détection de secousses
            Accelerometer.Default.ShakeDetected += Accelerometer_ShakeDetected;
            Accelerometer.Default.Start(SensorSpeed.Default);
        }
        else
        {
            // Désactiver la détection
            Accelerometer.Default.Stop();
            Accelerometer.Default.ShakeDetected -= Accelerometer_ShakeDetected;

            // Réinitialiser la couleur
            shakeColor = "Black";
            shakeIndicator.Color = Colors.Black;
        }
    }
}

Points importants:

Méthode observateur

private void Accelerometer_ShakeDetected(object sender, EventArgs e)
{
    // Changer la couleur en rouge lors d'une secousse
    shakeColor = "Red";

    // Mettre à jour l'UI sur le thread principal
    MainThread.BeginInvokeOnMainThread(() =>
    {
        shakeIndicator.Color = Colors.Red;
    });
}

Explication:

Le carré va donc changer de couleur lorsqu'une secousse est détectée.

Simulateur

Pour simuler une secousse avec l'émulateur, le plus simple est d'envoyer une commande:

adb emu sensor set acceleration 100:100:100 && timeout 1 > NUL && adb emu sensor set acceleration 0:0:0

Suite à cet exercice, les compétences suivantes ont été travaillées: